package org.fjsei.yewu.jpa;

import md.specialEqp.inspect.Detail;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.NoRepositoryBean;

import java.util.UUID;

/**
 * Dynamic Projections
补充Repository接口，支持没有count()的分页Slice，实体动态投影，
 但是，这里没有单独写个 ProjectionRepositoryImpl 实现类！
 并且也和@EnableJpaRepositories(repositoryBaseClass, repositoryFactoryBeanClass)没有一点关系！
 似乎完全是框架支持的动态？ 也不能随意添加参数的，函数名字也不是完全随意的。 Query creation from method names
 依名字定义查询 https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.named-queries
 Pageable and Sort 两个特殊参数。
 实现类必须按规定名字来： postfix defaults to Impl.  # 特殊SpEL注入的参数from #{#entityName} t
 竟然org.springframework.data.projection.ProxyProjectionFactory只是对JPA查询以后返回结果去做的投影？根本不是查询前select字段的过滤方案。
 【用处】目的是投影select出来字段减少可提高性能；#但若想要过滤条件 && 支持no count()的话，就只能去看QuerydslPredicateExecutor了，这个ProjectionRepository无法支持。
*/

@NoRepositoryBean
public interface ProjectionRepository<T,ID>  extends CrudRepository<T, ID> {
   // Page<T> findAll(Predicate predicate, Pageable pageable);

    /** Dynamic Projections #就缺不能够定义过滤条件。
     * 这样就能免于 count()计算耗时；参数 Class<P> type用于实体类的动态投影;
     *通过具体的仓库操作接口定义： interface StoreSyncRepository extends  ProjectionRepository<StoreSync, UUID>
     *来实现 ProjectionRepository 的readAllBy方法 的真正实现。
     *【特殊】type的接口UnitPi定义注意要纯粹的，不要添加extends FactoryExpression，也不要UnitDto implements UnitPi，否则投影失效;
     * 允许不需要套排序的pageable；
     * */
    <P> Slice<P>  readAllBy(Pageable pageable, Class<P> type);

    //也不能随意定义的报错At least 1 parameter(s) provided but only 0 parameter(s) present in query.
    //<P> Slice<P>  readAllBy(Predicate predicate, Pageable pageable, Class<P> type);
    //Slice<Detail> readAllOrderByIdAsc(Pageable pageable, Class<?> type); 失败 不能识别最后的asc desc;

    //【提升性能】添加上主键的排序范围搜索比默认做的findAll(page)更快！Id排序 范围 搜索[分两段]
    <P> Slice<P>  findAllByIdBetween(ID id1, ID id2, Pageable pageable, Class<P> type);

   //<S extends T, R> R findBy(Predicate predicate, Function<FluentQuery.FetchableFluentQuery<S>, R> queryFunction);

  // @Query("select u from User u where u.firstname = ?1 and u.firstname=?#{[0]} and u.emailAddress = ?#{principal.emailAddress}")
  //  List<User> findByFirstnameAndCurrentUserWithCustomQuery(String firstname); 特殊SpEL注入的参数
  //声明的按名字自动生成代码的函数{和QuerydslPredicateExecutor不是一条路子的}，报错At least 1 parameter(s) provided but only 0 parameter(s) present in query.
    //<P> Slice<P>  readAllBy(Predicate predicate, Pageable pageable, Class<P> type);

    //排序id> null ,投影。 非得加一个参数ID id,?
//    <P> Slice<P> findAllOrderById(ID id,Pageable pageable, Class<P> type);

    //排序id> :id ,投影。支持深度翻页 searchAfter 提高性能。
 //   <P> Slice<P> findAllByIdGreaterThanOrderByIdAsc(ID id, Pageable pageable, Class<P> type);

    <P> Slice<P> findAllByIdGreaterThanOrderByIdAsc(ID id, Pageable pageable, Class<P> type);
    //直接加Predicate predicate或者Specification<Detail> spec,都报错At least 2 parameter(s) provided but only 1 parameter(s) present in query.
    <P> Slice<P> findAllByOrderById(Pageable pageable, Class<P> type);
}



/*
默认CRUD methods on repository instances inherited from SimpleJpaRepository are transactional. For read operations, the transaction configuration readOnly flag is set to true.
@Entity
@EntityListeners(AuditingEntityListener.class)  #JPA Auditing
class SpringSecurityAuditorAware implements AuditorAware<User> {
  @Override
  public Optional<User> getCurrentAuditor() {;  审计
* */
